package primegen.candidate.generation.impl



import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import primegen.candidate.generation.IGenCoordinator;

class GenCoordinator implements IGenCoordinator, Callable<Result>{

	class Result {

	}

	private ArrayList<Long> seedPrimes
	private long nextCandidate
	long swathSize

	ExecutorService coordinatorExecutor;
	ExecutorService candidateGenerators = Executors.newFixedThreadPool(1)
	Future<Result>  coordinatorFuture;

	BlockingQueue<Future<ArrayList<Long>>> producerFutures = new ArrayBlockingQueue<Future<ArrayList<Long>>>(5)

	GenCoordinator(final ArrayList<Long> seedPrimes) {
		this.seedPrimes = seedPrimes

		nextCandidate = seedPrimes.last() + 2L
		swathSize = 100000L
		println 'Using [' + seedPrimes.size + '] primes as a seed.'
		println 'Starting search at: ' + nextCandidate
	}

	def start() {
		synchronized (this) {
			if (coordinatorExecutor) {
				coordinatorExecutor = Executors.newSingleThreadExecutor();
				coordinatorFuture = coordinatorExecutor.submit(this);
			}
		}
	}

	def stop() {
		synchronized (this) {
			if (coordinatorExecutor && !coordinatorExecutor.isShutdown()) {
				coordinatorExecutor.shutdown()
				coordinatorFuture.cancel(true)
			}
		}
	}

	Result call() {
		try {
			while (nextCandidate < 1000000L && !coordinatorExecutor.isShutdown()) {
				BaseGenerator baseGenerator = new BaseGenerator(seedPrimes, nextCandidate, (nextCandidate += swathSize) -1)
				Future<ArrayList<Long>> future = candidateProducers.submit(baseGenerator);
				producerFutures.put(future)
			}
		}
		catch (InterruptedException ie) {
		}
		catch (Throwable t) {
			println t
		}
		finally {
			synchronized (this) {
				if (coordinatorExecutor.isShutdown()) {
					println 'GenCoordinator Task Shutting down .....'
				}
				else {
					// submit a future task to replace this one. ?? kludge?
					coordinatorFuture = coordinatorExecutor.submit(this);
				}

				return "result";
			}
		}

	}
}